/**
 * 
 * @brief  .c
 * @param  None
 * 
 * @author xhq
 * @date   2024/12/12
 * 
 */
/* include */
#include "rpmsg_modules.h"
#include "util_factory.h"
#include "app_thread_modules.h"
/* define */

/* typedef */

/* global variebles */
rpmsg_recv_protocol_info_type g_rpmsg_recv_info = {
	.remote_endpt          =   REMOTE_ENDPT,
	.local_endpt           =   RPMSG_ADDR_ANY,
	.rproc_info[DSP_C71_0].rproc_id    =   DSP_C71_0,
	.rproc_info[DSP_C71_0].dev_name    =   NULL,
	.rproc_info[DSP_C71_1].rproc_id    =   DSP_C71_1,
	.rproc_info[DSP_C71_1].dev_name    =   NULL,
};

/* 指令 */
rpmsg_config_param_type g_rpmsg_config_param = {0};
rpmsg_status_param_type g_rpmsg_status_param = {0};

/* function */
int send_msg(int fd, char *msg, int len)
{
	int ret = 0;

	ret = write(fd, msg, len);
	if (ret < 0) {
		// perror("Can't write to rpmsg endpt device\n");
		return -1;
	}

	return ret;
}

int recv_msg(int fd, int len, char *reply_msg, int *reply_len)
{
	int ret = 0;

	/* Note: len should be max length of response expected */
	ret = read(fd, reply_msg, len);
	if (ret < 0) {
		// perror("Can't read from rpmsg endpt device\n");
		return -1;
	} else {
		*reply_len = ret;
	}

	return 0;
}
/**
 * @brief rpmsg模块初始化
 * 
 * @param None ：
 * 
 * @return uint32_t ：0：正常，非0：错误代码
 * 
 * @note：
 */
uint32_t rpmsg_modules_init()
{
	pthread_t l_rpmsg_send_thread = 0, l_rpmsg_recv_thread = 0;
    uint32_t l_u32_ret = 0;
    uint8_t  l_u8_eptdev_name[32] = { 0 };
    uint8_t  l_u8_packet_buf[512] = { 0 };
	rproc_info_type * l_rproc_info = (void *)&g_rpmsg_recv_info.rproc_info[DSP_C71_0];

    /* 初始化rpmsg */
    if (rpmsg_char_init(NULL) != 0)
    {
        printf("rpmsg_char_init failed!\n");
        SET_ERROR_CODE(l_u32_ret, 0);
        goto error;
    }

    /* 打开rpmsg设备 */
    sprintf(l_u8_eptdev_name, "rpmsg-char-%d-%d", l_rproc_info->rproc_id, getpid());
    l_rproc_info->rcdev = rpmsg_char_open(l_rproc_info->rproc_id, 
										  l_rproc_info->dev_name, 
										  g_rpmsg_recv_info.local_endpt, 
										  g_rpmsg_recv_info.remote_endpt, 
										  l_u8_eptdev_name, 0);
	/* 判断是否创建失败 */
	if (!l_rproc_info->rcdev) 
    {
        printf("Can't create an endpoint device\n");
        SET_ERROR_CODE(l_u32_ret, 1);
        goto error;
    }

	/* 创建rpmsg发送线程 */
    pthread_create(&l_rpmsg_send_thread, NULL, rpmsg_send_protocol_thread, NULL);

	/* 创建rpmsg接收线程 */
    pthread_create(&l_rpmsg_recv_thread, NULL, rpmsg_recv_protocol_thread, NULL);

    error:
    RETURN_ERROR_CODE(l_u32_ret, __func__);
}
/**
 * @brief rpmsg模块去初始化
 * 
 * @param None ：
 * 
 * @return uint32_t ：0：正常，非0：错误代码
 * 
 * @note：
 */
uint32_t rpmsg_modules_deinit()
{
    uint32_t l_u32_ret = 0;
	rproc_info_type * l_rproc_info = (void *)&g_rpmsg_recv_info.rproc_info[DSP_C71_0];

	/* 关闭rpmsg char */
	l_u32_ret = rpmsg_char_close(l_rproc_info->rcdev);
	if (l_u32_ret < 0)
	{
		printf("Can't delete the endpoint device\n");
		SET_ERROR_CODE(l_u32_ret, 0);
		goto error;
	}

	error:
	/* 退出rpmsg */
	rpmsg_char_exit();

    RETURN_ERROR_CODE(l_u32_ret, __func__);
}
/**
 * @brief 获取rpmsg rproc结构体指针 
 * 
 * @param None ：
 * 
 * @return uint32_t ：0：正常，非0：错误代码
 * 
 * @note：
 */
rproc_info_type *get_rpmsg_rproc_info()
{
	return (rproc_info_type *)g_rpmsg_recv_info.rproc_info;
}
/**
 * @brief 获取rpmsg 状态参数结构体指针 
 * 
 * @param None ：
 * 
 * @return uint32_t ：0：正常，非0：错误代码
 * 
 * @note：
 */
rpmsg_status_param_type *get_rpmsg_status_param()
{
	return (rpmsg_status_param_type *)&g_rpmsg_status_param;
}
/**
 * @brief 获取rpmsg 配置参数结构体指针 
 * 
 * @param None ：
 * 
 * @return uint32_t ：0：正常，非0：错误代码
 * 
 * @note：
 */
rpmsg_config_param_type *get_rpmsg_config_param()
{
	return (rpmsg_config_param_type *)&g_rpmsg_config_param;
}
/**
 * @brief 设置rpmsg 配置参数结构体
 * 
 * @param None ：
 * 
 * @return uint32_t ：0：正常，非0：错误代码
 * 
 * @note：
 */
uint32_t update_rpmsg_config_param(rpmsg_config_param_type *l_rpmsg_config_param)
{
	memcpy(&g_rpmsg_config_param, l_rpmsg_config_param, sizeof(g_rpmsg_config_param));

	return 0;
}
/**
 * @brief 设置dsp参数信息
 * 
 * @param None ：
 * 
 * @return uint32_t ：0：正常，非0：错误代码
 * 
 * @note：
 */
uint32_t dsp_rpmsg_set_config_info(rproc_info_type * l_rproc_info, uint8_t l_u8_info_page_num)
{
	int32_t  l_i32_error = 0;
	uint32_t l_u32_ret = 0;
	uint32_t l_u32_idx = 0;
	uint8_t l_u8_send_buf[RPMSG_EXCHANGE_BUF_SIZE] = {0};

	rpmsg_config_param_type *l_rpmsg_config_param = &g_rpmsg_config_param;
	l_rpmsg_config_param->config_info.cmd_page_num = l_u8_info_page_num;

	/* 申请互斥锁 */
	pthread_mutex_lock(&g_dsp_param_semaphore);

	/* 命令号 */
	*(uint16_t *)&l_u8_send_buf[l_u32_idx] = RPMSG_HEAD;
	l_u32_idx += 2;

	/* 数据长度 */
	l_u32_idx += 2;

	/* 指令页码 */
	l_u8_send_buf[l_u32_idx++] = l_rpmsg_config_param->config_info.cmd_page_num;

    /* 数据处理使能 */
	l_u8_send_buf[l_u32_idx++] = l_rpmsg_config_param->config_info.data_pro_enable;

    /* 参数配置使能 */
	l_u8_send_buf[l_u32_idx++] = l_rpmsg_config_param->config_info.config_param_enable;
    
	/* 信号处理模式 */
	l_u8_send_buf[l_u32_idx++] = l_rpmsg_config_param->config_info.signal_pro_mode;

	/* 数据内容 */
	switch (l_u8_info_page_num)
	{
		case 0x00:
		{
			memcpy((uint8_t *)&l_u8_send_buf[l_u32_idx], (uint8_t *)&g_rpmsg_config_param.rpmsg_page0_config_param, 
			        sizeof(g_rpmsg_config_param.rpmsg_page0_config_param));
			l_u32_idx += sizeof(g_rpmsg_config_param.rpmsg_page0_config_param);
			break;
		}
		case 0x01:
		{
			break;
		}
		default:
			break;
	}

	/* 校验 */
	l_u32_idx += 2;

	/* 帧尾 */
	*(uint16_t *)&l_u8_send_buf[l_u32_idx] = RPMSG_TAIL;
	l_u32_idx += 2;

	/* 数据长度 */
	*(uint16_t *)&l_u8_send_buf[2] = (uint16_t)l_u32_idx;

	/* 发送数据 */
	l_i32_error = send_msg(l_rproc_info->rcdev->fd, (char *)l_u8_send_buf, l_u32_idx);
	if (l_i32_error < 0)
	{
		printf("rpmsg send msg error!\n");
		SET_ERROR_CODE(l_u32_ret, 0);
	}

	error:
	/* 释放互斥锁 */
    pthread_mutex_unlock(&g_dsp_param_semaphore);

	RETURN_ERROR_CODE(l_u32_ret, __func__);
}


struct timespec test_timespec_start = {0};
struct timespec test_timespec_end = {0};
/**
 * @brief 获取dsp状态信息
 * 
 * @param None ：
 * 
 * @return uint32_t ：0：正常，非0：错误代码
 * 
 * @note：
 */


uint32_t dsp_rpmsg_get_status_info(rproc_info_type * l_rproc_info, uint8_t *l_u8_recv_buf)
{
	uint8_t  l_u8_cmd_page_num = 0, l_u8_data_pro_complete_flag = 0;
	uint16_t l_u16_rpmsg_head = 0, l_u16_recv_buf_size = 0, l_u16_check_value = 0;
	int32_t  l_i32_error = 0;
	uint32_t l_u32_ret = 0, l_u32_idx = 0;
	uint8_t l_u8_send_buf[RPMSG_EXCHANGE_BUF_SIZE] = {0};
    uint32_t l_waiting_time_ms = 0;
	rpmsg_status_param_type *l_rpmsg_status_param = &g_rpmsg_status_param;

    char filename[100] = {0};
    static uint32_t s_u32frame_cnt = 0;


	/* 申请互斥锁 */
	pthread_mutex_lock(&g_dsp_param_semaphore);

	/* 检查参数合法性 */
	if ((l_rproc_info == NULL) || (l_u8_recv_buf == NULL))
	{
		printf("l_rproc_info or l_u8_recv_buf invalid param!\n");
		SET_ERROR_CODE(l_u32_ret, 0);
		goto error;
	}

	/* 帧头 */
	l_u16_rpmsg_head  = *(uint16_t *)&l_u8_recv_buf[l_u32_idx]; 
	if (l_u16_rpmsg_head != RPMSG_HEAD)
	{
		printf("rpmsg recv head error!\n");
		SET_ERROR_CODE(l_u32_ret, 1);
		goto error;
	}
	l_u32_idx += 2;

	/* 数据长度 */
	l_u16_recv_buf_size = *(uint16_t *)&l_u8_recv_buf[l_u32_idx]; 
	if ((l_u16_recv_buf_size < 0) || (l_u16_recv_buf_size > RPMSG_EXCHANGE_BUF_SIZE))
	{
		printf("rpmsg recv size error!\n");
		SET_ERROR_CODE(l_u32_ret, 1);
		goto error;
	}
	l_u32_idx += 2;

	/* 校验 */
	// l_u8_recv_buf[l_u16_recv_buf_size - 4]
	// l_u16_check_value = bcc();    // 帧头到数据内容

    /* 指令页码 */
	l_rpmsg_status_param->status_info.cmd_page_num = l_u8_recv_buf[l_u32_idx++];

	/* 数据处理完成标志位 */
	l_rpmsg_status_param->status_info.data_pro_complete_flag = l_u8_recv_buf[l_u32_idx++];

	/* 释放信号量 */
	if (l_rpmsg_status_param->status_info.data_pro_complete_flag == DSP_PRO_COMPLETE)
	{
		sem_post(&g_dsp_pro_comlete_semaphore);
		clock_gettime(CLOCK_MONOTONIC_RAW, &g_timespec_end); 

#if 0 
		creat_file_name("/home/zzg/mmv_app/target_data",0,s_u32frame_cnt++,filename);
		write_file(filename,g_obj_info_pu8_mmap,sizeof(object_info_type),1);
 #endif 
	
	/* debug */
	printf("[warm]DSP_PRO_COMPLETE :%d\r\n", (g_timespec_end.tv_sec - g_timespec_start.tv_sec) * 1000 + 
							(g_timespec_end.tv_nsec - g_timespec_start.tv_nsec) / 1000000);

	}

	/* 数据配置/查询返回代码 */
	l_rpmsg_status_param->status_info.param_config_ret_code = l_u8_recv_buf[l_u32_idx++];
   
    /* 保留*/
    l_u32_idx += 1;

	/* 数据内容 */
	switch (l_rpmsg_status_param->status_info.cmd_page_num)
	{
		case 0x00:
		{
			memcpy((uint8_t *)&l_rpmsg_status_param->rpmsg_page0_status_param, (uint8_t *)&l_u8_recv_buf[l_u32_idx], 
			        sizeof(l_rpmsg_status_param->rpmsg_page0_status_param));
			l_u32_idx += sizeof(l_rpmsg_status_param->rpmsg_page0_status_param);

			// // test
			// printf("[info]mmv-lidar-%d-%d-%d-%d\n", g_rpmsg_status_param.rpmsg_page0_status_param.num,
			//                                   g_rpmsg_status_param.rpmsg_page0_status_param.year,
			// 								  g_rpmsg_status_param.rpmsg_page0_status_param.month,
			// 								  g_rpmsg_status_param.rpmsg_page0_status_param.day);

			// printf("[info]dsp_debug_param1:%d, %d, %d, %d, %d\n", 
			//                                        g_rpmsg_status_param.status_info.cmd_page_num,
			// 									   g_rpmsg_status_param.status_info.data_pro_complete_flag,
			// 									   g_rpmsg_status_param.rpmsg_page0_status_param.dsp_debug_param1,
			//                                        g_rpmsg_status_param.rpmsg_page0_status_param.dsp_debug_param2,
			// 									   g_rpmsg_status_param.rpmsg_page0_status_param.dsp_debug_param3);

			break;
		}
		case 0x01:
		{
			break;
		}
		default:
			break;
	}

	error:
	/* 释放互斥锁 */
    pthread_mutex_unlock(&g_dsp_param_semaphore);

	RETURN_ERROR_CODE(l_u32_ret, __func__);
}
/**
 * @brief rpmsg发送msg通知dsp处理数据
 * 
 * @param None ：
 * 
 * @return uint32_t ：0：正常，非0：错误代码
 * 
 * @note：
 */
int32_t dsp_rpmsg_set_data_pro_msg()
{
	rproc_info_type * l_rproc_info = (void *)&g_rpmsg_recv_info.rproc_info[DSP_C71_0];
	rpmsg_config_param_type *l_rpmsg_config_param = get_rpmsg_config_param();

	/* 设置数据处理使能 */
	l_rpmsg_config_param->config_info.data_pro_enable = 1;
	update_rpmsg_config_param(l_rpmsg_config_param);

	/* 发送数据处理msg至dsp */
	dsp_rpmsg_set_config_info(l_rproc_info, 0);

	/* 若数据处理标志位使能，发送完成后清除 */
	if (l_rpmsg_config_param->config_info.data_pro_enable == 1)
	{
		l_rpmsg_config_param->config_info.data_pro_enable = 0;
		update_rpmsg_config_param(l_rpmsg_config_param);
	}
}
/**
 * @brief rpmsg接收协议解析线程
 * 
 * @param None ：
 * 
 * @return uint32_t ：0：正常，非0：错误代码
 * 
 * @note：
 */
void *rpmsg_recv_protocol_thread()
{
	int32_t l_int32_i = 0, l_int32_ret = 0;
	uint8_t l_u8_recv_buf[RPMSG_EXCHANGE_BUF_SIZE] = { 0 };
	uint32_t l_u32_packet_len = sizeof(l_u8_recv_buf);
	rproc_info_type * l_rproc_info = (void *)&g_rpmsg_recv_info.rproc_info[DSP_C71_0];

	while (1)
	{
		/* 接收rpmsg数据包 */
    	l_int32_ret = recv_msg(l_rproc_info->rcdev->fd, RPMSG_EXCHANGE_BUF_SIZE, (char *)l_u8_recv_buf, &l_u32_packet_len);

		if (l_int32_ret == 0)
		{
			dsp_rpmsg_get_status_info(l_rproc_info, l_u8_recv_buf);
		}

		// debug info
		#if (0)
		// printf("[warn]rpmsg recv thread!\n");		
		#endif
	}
} 
/**
 * @brief rpmsg接收协议解析线程
 * 
 * @param None ：
 * 
 * @return uint32_t ：0：正常，非0：错误代码
 * 
 * @note：
 */
void *rpmsg_send_protocol_thread()
{
	uint32_t l_u32_page_num_count = 0;
	rproc_info_type * l_rproc_info = (void *)&g_rpmsg_recv_info.rproc_info[DSP_C71_0];
	rpmsg_config_param_type *l_rpmsg_config_param = get_rpmsg_config_param();

	while (1)
	{
		l_rpmsg_config_param = get_rpmsg_config_param();

		dsp_rpmsg_set_config_info(l_rproc_info, l_u32_page_num_count);
		l_u32_page_num_count++;

        /* 配置到最大页 */
		if (l_u32_page_num_count >= RPMSG_CMD_PAGE_MAX)
		{
			l_u32_page_num_count = 0;
		}

		thread_mSleep(1000);

		// debug info
		#if (0)
		printf("dsp send thread:%d!\n", l_u32_page_num_count);			
		#endif

	}
}
